<!--
 * @Date: 2024-07-30 10:11:11
 * @Author: LiSong
 * @LastEditors: ljc
 * @LastEditTime: 2025-08-05 18:42:35
 * @Description: 
-->
<template>
  <static-content-wrapper v-show="designState ? true : !field.options.hidden"
    class="data-table-widget-wrapper"
    :class="[designStateClass]"
    :field="field"
    :designer="designer"
    :design-state="designState"
    :parent-list="parentList"
    :parent-widget="parentWidget"
    :display-style="field.options.displayStyle"
    :sub-form-row-id="subFormRowId"
    :sub-form-row-index="subFormRowIndex"
    :sub-form-col-index="subFormColIndex"
    :index-of-parent-list="indexOfParentList">
    <VfDataTable ref="vfTableDataRef"
      :="tableOptions"
      :title="tableStore.title"
      :params="queryParams"
      :columns="tableColumns"
      :designState="designState"
      @cellClick="cellClick"
      @currentChange="rowCurrentChange"
      @loaded="({total})=>totalCount = total">
      <template v-if="toolbarButtons"
        #toolbar_left>
        <template v-for="btn in toolbarButtons"
          :key="btn.id">
          <el-button v-if="buttonsVisible([btn], ['btn'], '工具栏')"
            :="{ ...btn }"
            @click="toolbarButtonsClick(btn)">
            <span>{{ btn.label }}</span>
          </el-button>
        </template>
      </template>
      <template #toolbar_right>
        <template v-if="sqlDataType">
          <el-input v-if="searchStore?.mhcxInput?.enabled"
            :="mhcxAttrs"
            class="toolbar-item"
            v-model="queryParams.params.mhcx"
            @change="mhcxInputChange">
          </el-input>
        </template>
        <template v-else>
          <el-input v-if="searchStore?.mhcxInput?.enabled"
            v-model="queryParams.mhcx"
            :="mhcxAttrs"
            class="toolbar-item"
            @change="mhcxInputChange">
          </el-input>
        </template>
      </template>
      <!-- 操作列 -->
      <template #operation="{ row }">
        <div class="operation-cell-body"
          :class="[
          operateColInfo.moreButtons.length > 0 ? 'flex' : ''
        ]">
          <template v-for="btn in operateColInfo.showButtons"
            :key="btn.id">
            <el-button v-if="buttonsVisible([btn, row], ['btn', 'row'], '操作列')"
              :="{ ...btn }"
              @click.stop="operateButtonsClick(btn, row)">
              <span>{{ btn.label }}</span>
            </el-button>
          </template>
          <el-dropdown class="operation-dropdown"
            teleported
            popper-class="operation-dropdown-popper"
            v-if="operateColInfo.moreButtons.length > 0">
            <span class="el-dropdown-link">
              <span>更多</span>
              <el-icon class="more-down-icon">
                <ArrowDown />
              </el-icon>
            </span>
            <template #dropdown>
              <el-dropdown-menu>
                <template v-for="btn in operateColInfo.moreButtons"
                  :key="btn.id">
                  <el-dropdown-item v-if="buttonsVisible([btn, row], ['btn', 'row'], '操作列')"
                    @click.stop="operateButtonsClick(btn, row)">
                    {{ btn.label }}
                  </el-dropdown-item>
                </template>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
        </div>
      </template>
    </VfDataTable>
  </static-content-wrapper>
</template>

<script>
import XEUtils from 'xe-utils';

import emitter from '@/utils/emitter';
import fieldMixin from '@designer/form-widget/field-widget/fieldMixin';
import StaticContentWrapper from './static-content-wrapper';

import { defAxios } from '@/utils/http'
import { fieldBaseMixin } from './mixins'
import { DataSourceType } from '@/base/pojo/DataSourceType.js'
import { TableColBoxType } from '@/base/pojo/TableColType.js'

import { VfUtils } from '@/utils/vf-utils'
import ParseUtils from '@/utils/parseUtils'
import TableUtils from '@/components/tables/cfg/table-utils.js'

import { ArrowDown } from '@element-plus/icons-vue'


import { VfDataTable } from '@/components/vf-table';


export default {
  name: 'data-table-widget',
  //必须固定为FieldWidget，用于接收父级组件的broadcast事件
  componentName: 'FieldWidget',
  mixins: [
    emitter,
    fieldMixin,
    fieldBaseMixin
  ],
  inject: ['enumsDataPools', 'axiosConfig'],
  components: {
    ArrowDown,
    VfDataTable,
    StaticContentWrapper,
  },
  props: {
    field: Object,
    designer: Object,
    parentList: Array,
    parentWidget: Object,
    indexOfParentList: Number,
    /** 是否为设计状态 */
    designState: { type: Boolean, default: false },
    /* 子表单组件行索引，从0开始计数 */
    subFormRowIndex: { type: Number, default: -1 },
    /* 子表单组件列索引，从0开始计数 */
    subFormColIndex: { type: Number, default: -1 },
    /* 子表单组件行Id，唯一id且不可变 */
    subFormRowId: { type: String, default: '' },
  },
  computed: {
    // 数据源类型
    sqlDataType() {
      return this.tableOptions.dataType === DataSourceType.SQL.value
    },
    // 模糊查询配置
    mhcxAttrs() {
      const { mhcxInput } = this.searchStore
      const resStyle = {}
      if (mhcxInput && mhcxInput.width) {
        resStyle['width'] = `${mhcxInput.width}px`
      } else {
        resStyle['width'] = '200px'
      }
      return {
        style: resStyle,
        clearable: mhcxInput.clearable === 'undefined' ? mhcxInput.clearable : true,
        placeholder: mhcxInput?.placeholder || '请输入'
      }
    },
    // 表格配置
    tableConfig() {
      return this.field.options.tableConfig
    },
    // 表格组件属性配置
    tableOptions() {
      return this.initTableAttrs();
    },
    // 工具栏按钮配置
    toolbarButtons() {
      const { toolbarConfig: { buttons } } = this.field.options;
      if (buttons && buttons.length > 0) {
        return buttons
      } else {
        return false
      }
    },
    /**
     * 操作列配置
     */
    operateColInfo() {
      const { dataConfig } = this.field.options;
      const { buttons, showNum } = dataConfig.operateColumn
      const showButtons = []
      const moreButtons = []
      for (let index = 0; index < buttons.length; index++) {
        const btnItem = buttons[index];
        if (!btnItem.visible) continue;
        if (index < showNum) {
          showButtons.push(btnItem)
        } else {
          moreButtons.push(btnItem)
        }
      }
      return {
        ...dataConfig.operateColumn,
        showButtons, moreButtons
      }
    },
    designStateClass() {
      return ''
    }
  },
  data() {
    return {
      tableAttrs: {},
      tableStore: {
        title: ''
      },
      searchStore: {},
      queryParams: { mhcx: void 0 },
      tableColumns: [],
      totalCount: 0,
    };
  },
  created() {
    this.registerToRefList();
    this.initEventHandler();
    this.handleOnCreated();
  },
  mounted() {
    this.handleOnMounted();

  },
  beforeUnmount() {
    this.unregisterFromRefList();
  },
  methods: {
    /**
     * 初始化表格的配置信息
     */
    initTableAttrs() {
      const { tableConfig, rowConfig } = this.field.options;
      // 唯一主键的字段名
      if (tableConfig.keyField) rowConfig['keyField'] = tableConfig.keyField
      // 表格的配置
      let tableAttrs = { ...tableConfig, rowConfig }
      // 初始化字段
      this.initColumns(tableAttrs)
      // 加载基本信息
      this.initTableBase(tableAttrs)
      // 加载数据源信息
      this.initDataSoure(tableAttrs)
      // 初始化序号配置
      this.initSeqConfig(tableAttrs)
      // 初始化选框配置
      this.initBoxConfig(tableAttrs)
      // 初始化合并函数
      this.initSpanMethod(tableAttrs)
      // 初始化单元格样式
      this.initCellClassName(tableAttrs)
      // 设置表格的高
      this.initTableHeight(tableAttrs)
      // 初始化分页配置
      this.initPagerConfig(tableAttrs)
      // 初始化查询条件
      this.initSearchConfig(tableAttrs)
      // 初始化表格工具栏
      this.initToolbarConfig(tableAttrs)
      // 解析请求成功后的执行方法
      this.initResponseHandle(tableAttrs)
      // 初始化模拟数据
      if (this.designState) {
        tableAttrs['data'] = TableUtils.generateTableData(this.tableColumns, tableAttrs)
      }
      return tableAttrs;
    },
    /**
     * 初始化表格的基础配置
     * @param tableAttrs 数据配置
     */
    initTableBase(tableAttrs) {
      const { designState } = this
      const { tableConfig } = this.field.options;
      // 设置样式类
      tableAttrs['class'] = designState ? 'data-table-design' : ''
      // 设置是否自动加载
      tableAttrs['autoLoad'] = designState ? false : tableConfig.autoLoad;
      // 设置表格标题
      this.tableStore.title = tableConfig.title
    },
    /**
     * 初始化表格的列配置
     */
    initColumns() {
      const { dataConfig, tableConfig } = this.field.options;
      const columns = [...dataConfig.fieldColumns]
      // 模拟一条数据
      if (tableConfig.showOperateCol && dataConfig.operateColumn) {
        let columnItem = dataConfig.operateColumn
        columnItem['visible'] = tableConfig.showOperateCol
        columns.push(columnItem)
      }
      this.tableColumns = columns
    },
    /**
     * 初始化序号配置
     */
    initSeqConfig(tableAttrs) {
      const { seqConfig } = this.field.options;
      tableAttrs['seqConfig'] = seqConfig
    },
    /**
     * 初始化选框配置
     */
    initBoxConfig(tableAttrs) {
      const { boxConfig } = this.field.options;
      if (XEUtils.isEmpty(boxConfig)) {
        tableAttrs['boxConfig'] = false
      } else {
        if (boxConfig.enabled) {
          tableAttrs['boxConfig'] = boxConfig
        } else {
          tableAttrs['boxConfig'] = false
        }
      }
    },
    /**
     * 初始化数据源配置
     *
     * @param dataConfig 数据配置
     * @returns 解析后的配置
     */
    initDataSoure(tableAttrs) {
      const { dataConfig } = this.field.options;
      let reqConfig = {}
      if (dataConfig.mode === DataSourceType.REQ.value) {
        reqConfig = this.parseDataSoureByREQ(dataConfig);
        delete tableAttrs?.data;
      }
      if (dataConfig.mode === DataSourceType.SQL.value) {
        reqConfig = this.parseDataSoureBySQL(dataConfig);
        delete tableAttrs?.data;
      }
      if (dataConfig.mode === DataSourceType.STA.value) {
        reqConfig = this.parseDataSoureBySTA(dataConfig);
      }
      Object.assign(tableAttrs, {
        ...tableAttrs, ...reqConfig,
        dataType: dataConfig.mode,
        request: this.axiosConfig.request || defAxios,
      })
    },
    /**
     * 初始化合并函数
     * 
     * @param tableAttrs 表格属性
     */
    initSpanMethod(tableAttrs) {
      if (tableAttrs.spanMethodFunc) {
        const paramsName = ['row', 'rowIndex', 'column', 'columnIndex', 'data', 'visibleData']
        tableAttrs['spanMethod'] = (params) => {
          try {
            const paramsValue = paramsName.map(key => params[key])
            const executeFunc = new Function(...paramsName, tableAttrs.spanMethodFunc.replace('func:', ''))
            const result = executeFunc.call(this, ...paramsValue)
            return result
          } catch (error) {
            console.error('解析合并函数配置出错，请检查内容！', error)
            delete tableAttrs.spanMethod
          }
        }
      } else {
        delete tableAttrs.spanMethod
      }
    },
    /**
     * 初始化单元格样式配置
     * 
     * @param tableAttrs 表格属性
     */
    initCellClassName(tableAttrs) {
      if (tableAttrs.cellClassNameFunc) {
        const paramsName = ['row', 'rowIndex', 'column', 'columnIndex', 'data', 'visibleData']
        tableAttrs['cellClassName'] = (params) => {
          try {
            const paramsValue = paramsName.map(key => params[key])
            const executeFunc = new Function(...paramsName, tableAttrs.cellClassNameFunc.replace('func:', ''))
            const result = executeFunc.call(this, ...paramsValue)
            return result
          } catch (error) {
            console.error('解析单元格样式类出错，请检查内容！', error)
            delete tableAttrs.cellClassName
          }
        }
      } else {
        delete tableAttrs.cellClassName
      }
    },
    /**
     * 初始化分页配置
     */
    initPagerConfig(tableAttrs) {
      const { pagerConfig } = this.field.options;
      if (XEUtils.isEmpty(pagerConfig)) return
      let pageSizes = pagerConfig.pageSizes
      if (pageSizes.length === 0) { pageSizes = [10, 20, 50, 100] }
      tableAttrs['pagerConfig'] = { ...pagerConfig, pageSizes }
    },
    /**
     * 初始化表格高度属性
     * @returns {Object} 解析后的数据
     */
    initTableHeight(tableAttrs) {
      const { designState } = this
      const { height, minHeight } = tableAttrs
      const resStyle = {}
      const resMinHeight = minHeight || 100
      // 设置最小高度
      tableAttrs.minHeight = resMinHeight
      if (!height || ['auto', '100%'].includes(height)) {
        resStyle['height'] = '100%'
        tableAttrs.height = 'auto'
      } else {
        let resHeight = height
        if (XEUtils.isString(resHeight) && (resHeight.endsWith('px') || resHeight.endsWith('%'))) {
          resHeight = height
        } else {
          resHeight = Number(height)
          if (XEUtils.isNaN(resHeight)) {
            resHeight = 'auto'
            console.warn('表格高度不符合规则[数字、XX(px|%)]，请检查')
          } else {
            resHeight = resHeight ? `${resHeight}px` : 'auto'
          }
        }
        resStyle['height'] = (resHeight === 'auto') ? 'auto' : resHeight
        tableAttrs.height = resHeight
      }
      if (!designState) return
      tableAttrs['style'] = resStyle
    },
    /**
     * 初始化表格查询配置
     * 
     * @param tableAttrs 表格参数
     */
    initSearchConfig(tableAttrs) {
      const { searchConfig } = this.field.options;
      tableAttrs['amtUnitSelect'] = searchConfig ? searchConfig.dwSelect : {}
      this.searchStore['mhcxInput'] = searchConfig ? searchConfig.mhcxInput : {}
    },
    /**
     * 初始化表格工具栏
     */
    initToolbarConfig(tableAttrs) {
      const { toolbarConfig } = this.field.options;
      if (XEUtils.isEmpty(toolbarConfig)) return
      tableAttrs['toolbarConfig'] = toolbarConfig
    },
    /**
     * 初始化数据请求后可执行的方法
     */
    initResponseHandle(tableAttrs) {
      const { responseHandle } = tableAttrs
      if (responseHandle) {
        tableAttrs['responseHandle'] = (tableData) => {
          return this.parseTableRespHandle(responseHandle, tableData)
        }
      } else {
        delete tableAttrs.responseHandle
      }
    },
    /**
     * 解析请求的数据源配置
     * 
     * @param {Object} dataConfig 数据配置
     * @returns {Object} 解析后的配置
     */
    parseDataSoureByREQ({ reqConfig }) {
      // 解析查询参数
      const coverParams = this.parseQueryCondition(reqConfig.params);
      // 参数赋值
      this.queryParams = coverParams || {}
      return {
        method: reqConfig.method,
        dataUrl: reqConfig.url || '',
        paramsType: reqConfig.paramsType,
        restful: reqConfig.restful || false,
      };
    },
    /**
     * 解析SQL请求的数据源配置
     * 
     * @param {Object} dataConfig 数据配置
     * @returns {Object} 解析后的配置
     */
    parseDataSoureBySQL({ sqlConfig, paramColumns }) {
      const { hooks } = this.getBusiConfig()
      try {
        // 解析并封装参数
        const coverParams = { params: {} }
        const { content: sqlContent } = sqlConfig
        let encryptContent = sqlContent
        if (hooks && hooks.useCryptoHook) {
          encryptContent = hooks.useCryptoHook().encryptProcessSQL(sqlContent)
        } else {
          encryptContent = VfUtils.encryptToBase64(sqlContent)
        }
        coverParams['content'] = encryptContent
        paramColumns.forEach(item => {
          const renderParam = this.parseQueryCondition(item.paramRender) || ''
          let finalParam = item.defaultValue || renderParam
          finalParam = ParseUtils.parseValueByType(finalParam, item.kind)
          coverParams.params[item.field] = finalParam
        })
        // 参数赋值
        this.queryParams = coverParams || {}
        return sqlContent ? {
          method: 'post',
          dataUrl: '/data/process',
          paramsType: 'data'
        } : { data: [] }
      } catch (error) {
        console.error('解析SQL请求出错！', error)
        return {
          data: []
        }
      }

    },


    /**
     * 解析静态数据的数据源配置
     * 
     * @param {Object} dataConfig 数据配置
     * @returns {Object} 解析后的配置
     */
    parseDataSoureBySTA({ staticConfig, paramColumns }) {
      const content = staticConfig.content || ''
      let result = []
      if (content) {
        try {
          const executeFunc = new Function(content.replace('func:', ''))
          result = executeFunc.call(this)
        } catch (error) {
          console.log(error)
        }
      }
      return {
        data: result
      };
    },

    /**
     * 处理表格按钮组显示隐藏
     * 
     * @param {Array} params 参数数据
     * @param {Array} paramsText 参数名称
     * @param {String} toolText 功能名称
     */
    buttonsVisible(params, paramsText, toolText) {
      if (this.designState) return true
      const btnItem = params[0]
      if (btnItem.visibleFunc) {
        try {
          const executeFunc = new Function(...paramsText, 'queryParams', btnItem.visibleFunc)
          const result = executeFunc.call(this, ...params, this.queryParams)
          return result
        } catch (error) {
          console.error(`解析表格${toolText}按钮显示隐藏方法出错！`, error)
          return true
        }
      } else {
        return btnItem.hasOwnProperty('visible') ? btnItem.visible : true
      }
    },
    /**
     * 模糊查询数据变化
     * 
     * @param value 输入的值
     */
    mhcxInputChange(value) {
      // 设计环境不加载数据
      if (this.designState) return
      if (!this.searchStore?.mhcxInput?.enabled) return
      if (!this.searchStore?.mhcxInput?.autoLoad) return
      this.handleSearch()
    },
    amtSelectChange(value) {
      // 设计环境不加载数据
      if (this.designState) return
      if (!this.searchStore?.amtUnitSelect?.enabled) return
      if (!this.searchStore?.amtUnitSelect?.autoLoad) return
      this.handleSearch()
    },
    /**
     * event 单元格点击事件
     * 
     * @param params 参数
     */
    cellClick(params) {
      this.handleOnTableFunc('onCellClick', params)
    },
    /**
     * event 行点击事件
     * 
     * @param params 参数
     */
    rowCurrentChange(params) {
      this.handleOnTableFunc('onCurrentChange', params)
    },
    /**
     * 工具栏按钮点击事件
     */
    toolbarButtonsClick(btnItem) {
      // 设计期间不触发事件
      if (this.designState) return
      const tableRef = this.$refs['vfTableDataRef']
      const widgetOption = this.field.options
      const { boxConfig } = widgetOption
      let checkedRows = []
      // 开启选框时
      if (boxConfig.enabled && TableColBoxType.RADIO.equals(boxConfig.mode)) {
        const row = tableRef.getRadioRecord()
        checkedRows = [row]
      }
      if (boxConfig.enabled && TableColBoxType.CHECKBOX.equals(boxConfig.mode)) {
        const rows = tableRef.getCheckboxRecords()
        checkedRows = rows
      }
      const funcType = 'onTableButtonsClick'
      const funcParamsName = ['btnItem', 'checkedRows', 'tableName']
      const funcParamsValue = [btnItem, checkedRows, widgetOption.name]
      try {

        if (widgetOption.hasOwnProperty(funcType) && !!widgetOption[funcType]) {
          let changeFn = new Function(...funcParamsName, widgetOption[funcType])
          changeFn.call(this, ...funcParamsValue)
        } else {
          this.formRenderDispatchEmit(funcType, funcParamsValue)
        }
      } catch (error) {
        console.error('解析表格按钮组操作方法数据出错！', error)
      }
    },
    /**
     * 操作按钮点击
     * 
     * @param btnItem 按钮信息
     * @param row 行数据
     */
    operateButtonsClick(btnItem, row) {
      // 设计期间不触发事件
      if (this.designState) return
      const funcType = 'onOperateButtonsClick'
      const widgetOption = this.field.options
      const funcParamsName = ['btnItem', 'row', 'tableName']
      const funcParamsValue = [btnItem, row, widgetOption.name]
      try {
        if (widgetOption.hasOwnProperty(funcType) && !!widgetOption[funcType]) {
          const executeFn = new Function(...funcParamsName, widgetOption[funcType])
          executeFn.call(this, ...funcParamsValue)
        } else {
          this.formRenderDispatchEmit(funcType, funcParamsValue)
        }
      } catch (error) {
        console.error('解析表格操作按钮组操作方法数据出错！', error)
      }
    },
    /**
     * 表格查询
     */
    handleSearch() {
      this.$nextTick(() => {
        this.$refs['vfTableDataRef'].searchEvent()
      })
    },

    /**
     * 获取表格数据
     */
    getTableData() {
      return this.$refs['vfTableDataRef'].getTableData()
    },
    /**
     * 重载表格表格数据
     * 
     * @param params 参数信息
     */
    loadTableData(params = {}, reset = false) {
      // 设计环境不加载数据
      if (this.designState) return
      setTimeout(() => {
        const { queryParams } = this
        const { dataConfig } = this.field.options;
        let newParams = {}
        // SQL模式 参数结构封装 { params: {}, content: '' }
        if (dataConfig.mode === DataSourceType.SQL.value) {
          newParams = { params: { ...(queryParams.params || {}), ...(params || {}) } }
        } else {
          newParams = params
        }
        this.queryParams = { ...this.queryParams, ...newParams }
        this.$refs['vfTableDataRef'].searchEvent()
      }, 300)
    },
    /**
     * 获取单选数据
     */
    getRadioRecord() {
      return this.$refs['vfTableDataRef'].getRadioRecord()
    },
    /**
     * 获取多选数据
     */
    getCheckboxRecords() {
      return this.$refs['vfTableDataRef'].getCheckboxRecords()
    },
    /**
   * 获取表格数据的总数
   */
    getTableTotalCount() {
      return this.totalCount
    },
    /**
     * 设置表格标题
     * 
     * @param content 内容
     */
    setTableTitle(content) {
      const { tableConfig } = this.field.options;
      this.tableStore.title = content || tableConfig.title
    },
    /**
     * func 设置表格是否隐藏
     * 
     * @param hideCols 需要隐藏的字段
     * @param hidden 是否隐藏
     */
    setTableColumnHidden(hideCols = [], hidden) {
      hideCols = hideCols || []
      if (!hideCols.length) return
      const oldCols = XEUtils.clone(this.tableColumns, true)
      const newCols = []
      for (let col of oldCols) {
        if (hideCols.includes(col.field)) { col.visible = !hidden }
        newCols.push(col)
      }
      this.tableColumns = newCols
    },
    // 刷新数据
    reloadData(tableData){
      const tableRef = this.$refs['vfTableDataRef']
      tableRef.reloadData(tableData)
    },
    // 获取数据
    getFooterData(){
      const tableRef = this.$refs['vfTableDataRef']
      return tableRef.getFooterData()

    }
  },
};
</script>

<style lang="scss" scoped>
.data-table-widget-wrapper {
  height: 100%;
  :deep(.static-content-item) {
    height: 100%;
  }
}
</style>
<style lang="scss">
.data-table-widget-wrapper {
  .data-table-design {
    height: 100%;
    display: flex;
    flex-direction: column;
    .vxe-table {
      flex: 1;
      min-height: 100px;
    }
    .vxe-table--border-line {
      border: var(--vxe-table-border-width) solid var(--vxe-table-border-color) !important;
    }
  }
  .operation-cell-body {
    height: 100%;
    &.flex {
      display: flex;
      align-items: center;
    }
    .el-button + .el-button,
    .operation-dropdown {
      margin-left: 8px;
    }
    .more-down-icon {
      margin-left: 2px;
    }
  }
}
.el-dropdown-link {
  cursor: pointer;
  color: var(--el-color-primary);
  display: flex;
  align-items: center;
}
.operation-dropdown-popper {
  z-index: 9999 !important;
}
</style>